﻿using System;

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;

using System.Threading;
using System.Media;
using EOffice.Business;

namespace EOffice.Presentation
{
    public partial class frmChat : Form
    {
        const int PORT = 4000;
        private frmPrivateChat privateroom;
        private frmPrivateChat[] privates;

        private int privateroomnumber = 10;
        private Thread threadudp;
        private Thread thrCheckOnline;
        private Thread thrKeepAlive;
        private String sLocalUser;
        private String[] Messages;
        private UdpClient UdpClient;
        private EOffice.Business.cUserOnline UserOnline;
        private int MessageNumber = 100;
        private IPEndPoint ReceivePort;
        private int MessageColor = 5;
        private int FontTypeNum = 0;
        private int BItype = 0;
        private IPAddress IPLocalHost;
        private IPEndPoint IPLocalEndPoint;

        public frmChat()
        {
            InitializeComponent();

            Messages = new String[MessageNumber + 15];
            //Phòng chat riêng.
            privates = new frmPrivateChat[privateroomnumber];

            IPHostEntry iphostentry = Dns.GetHostEntry(Dns.GetHostName());
            foreach (IPAddress ipaddress in iphostentry.AddressList)
            {
                IPLocalHost = ipaddress;
            }
            IPLocalEndPoint = new IPEndPoint(IPLocalHost, PORT);
            ReceivePort = new IPEndPoint(new IPAddress(0), (0));
        }

        public void waitForPackets()
        {
            while (true)
            {
                try
                {
                    byte[] data = UdpClient.Receive(ref ReceivePort);
                    IPEndPoint newuser = new IPEndPoint(ReceivePort.Address, ReceivePort.Port);

                    if (System.Text.Encoding.Unicode.GetString(data)[0] == 'S')
                    {
                        int x = Convert.ToInt32(System.Text.Encoding.Unicode.GetString(data).Substring(4, 2));

                        if (x > privateroomnumber)
                            privateroomnumber = x;
                        UserOnline.AddNewUser(newuser, System.Text.Encoding.Unicode.GetString(data).Substring(6), System.Text.Encoding.Unicode.GetString(data).Substring(1, 3));
                        // also check messages
                        if (!UserOnline.CheckNumberOfMessage(System.Text.Encoding.Unicode.GetString(data).Substring(1, 3), newuser))
                        {
                            SendMessageNumber(newuser, UserOnline.GetNumberOfMessage(UserOnline.CheckNewNum(newuser)));
                        }
                        Onlines();
                    }

                    if (System.Text.Encoding.Unicode.GetString(data)[0] == 'M')
                    {
                        if (!UserOnline.FindUserName(newuser).Equals(sLocalUser))
                        {
                            if (UserOnline.CheckNumberOfMessage(System.Text.Encoding.Unicode.GetString(data).Substring(1, 3), newuser))
                            {
                                // broadcast send again in some computer
                                UserOnline.SetMessageNumber(UserOnline.CheckWithIp(newuser));
                                publicroom.WriteMessage(UserOnline.FindUserName(newuser) + System.Text.Encoding.Unicode.GetString(data).Substring(4), MessageColor, FontTypeNum, BItype);
                            }
                            else
                            {
                                SendMessageNumber(newuser, UserOnline.GetNumberOfMessage(UserOnline.CheckNewNum(newuser)));
                            }
                        }
                        UserOnline.MakeActive(UserOnline.CheckWithIp(newuser));
                        Onlines();
                    }
                    if (System.Text.Encoding.Unicode.GetString(data)[0] == 'R')
                    {
                        if (System.Text.Encoding.Unicode.GetString(data)[1] == 'R')
                        {
                            //MessageBox.Show("Sonradan gelmistir" + System.Text.Encoding.Unicode.GetString(data).Substring(5));
                            if (!sLocalUser.Equals(UserOnline.FindUserName(newuser)))
                            {
                                UserOnline.SetMessageNumber(UserOnline.CheckWithIp(newuser));
                                publicroom.WriteMessage(UserOnline.FindUserName(newuser) + System.Text.Encoding.Unicode.GetString(data).Substring(5), MessageColor, FontTypeNum, BItype);
                            }
                        }
                        if (System.Text.Encoding.Unicode.GetString(data)[1] == 'A')
                        {
                            SendMessageBefore(newuser, Convert.ToInt32(System.Text.Encoding.Unicode.GetString(data).Substring(2, 3)));
                        }
                    }
                    if (System.Text.Encoding.Unicode.GetString(data)[0] == 'P')
                    {
                        if (System.Text.Encoding.Unicode.GetString(data)[1] == 'R')
                        {
                            // re-sent private message
                        }
                        if (System.Text.Encoding.Unicode.GetString(data)[1] == 'E')
                        {
                            break;
                        }
                        if (System.Text.Encoding.Unicode.GetString(data)[1] == 'N')
                        {
                            // Normal message
                        }
                        if (System.Text.Encoding.Unicode.GetString(data)[1] == 'C')
                        {
                            // istenen eskik parcaya gelen cevap
                        }
                        if (System.Text.Encoding.Unicode.GetString(data)[1] == 'O')
                        {
                            OpenPrivateForm(Convert.ToInt32(System.Text.Encoding.Unicode.GetString(data).Substring(2, 2)), newuser);
                        }
                    }
                    if (System.Text.Encoding.Unicode.GetString(data)[0] == 'E')
                    {
                        UserOnline.DeleteUserPermanently(UserOnline.FindUserName(newuser), newuser);
                        publicroom.WriteMessage(UserOnline.FindUserName(newuser) + "đã thoát", MessageColor, FontTypeNum, BItype);
                        Onlines();
                    }
                }
                catch 
                {
                     UdpClient.Close();
                     threadudp.Abort();
                }
            }

        }
        public void Onlines()
        {
            int count = UserOnline.GetCount();
            cUser[] sArray = new cUser[count];
            sArray = UserOnline.GetOnlineUser();
            publicroom.DeleteTextBox3();
            for (int i = 0; i < count; i++)
            {
                // burda hata 1 out of range 
                if (sArray[i].GetPassive() == 1)
                {
                    //  WriteTextBoxOnlineUser(sArray[i].getUserName());
                    publicroom.WriteTextBoxOnlineUser(sArray[i].getUserName());
                }
            }
        }

        public void OpenPrivateForm(int a, IPEndPoint newuser)
        {
            privateroom = new frmPrivateChat();
            privateroom.Privareroomopen(a, newuser, sLocalUser, UserOnline.FindUserName(newuser));
            privateroom.Show();
        }

        public void CheckOnlines()
        {
            while (true)
            {
                try
                {
                    Thread.Sleep(60000);
                    int count = UserOnline.GetCount();
                    cUser[] sArray = new cUser[count];
                    sArray = UserOnline.GetOnlineUser();
                    for (int i = 0; i < count; i++)
                    {
                        // burda hata 1 out of range 
                        if (sArray[i].getActivity() == 1)
                        {
                            publicroom.WriteTextBoxOnlineUser(sArray[i].getUserName());
                        }
                    }
                }
                catch 
                {
                    thrCheckOnline.Join();
                    thrCheckOnline.Abort();
                }
            }
        }

        public void SendMessageNumber(IPEndPoint ip, int a)
        {
            try
            {
                byte[] sending = System.Text.Encoding.Unicode.GetBytes("RA" + a.ToString());
                UdpClient.Send(sending, sending.Length, ip);
            }
            catch (Exception E)
            {
                MessageBox.Show(E.ToString());
            }
        }

        public void SendMessageBefore(IPEndPoint ipendpoint, int start)
        {
            for (int i = start; i < MessageNumber; i++)
            {
                PNSendMessage(ipendpoint, Messages[i]);
            }
        }
        public void SendMessageUdp(string mes)
        {
            try
            {
                publicroom.WriteMessage(sLocalUser + ": " + mes, MessageColor, FontTypeNum, BItype);
                // her sey buraya
                Messages[MessageNumber++] = "M" + MessageNumber.ToString() + ":" + mes;
                Array.Resize(ref Messages, MessageNumber + 10);
                byte[] sending = System.Text.Encoding.Unicode.GetBytes("M" + MessageNumber.ToString() + ":" + mes);
                UdpClient.Send(sending, sending.Length, "255.255.255.255", 5000);

            }
            catch 
            {
                MessageBox.Show("You are not part of LAN");
            }
        }

        public void PNSendMessage(IPEndPoint ip, string a)
        {
            try
            {
                byte[] sending = System.Text.Encoding.Unicode.GetBytes("RR" + a.Substring(1));
                UdpClient.Send(sending, sending.Length, ip);
            }
            catch (Exception E)
            {
                MessageBox.Show(E.ToString());
            }
        }

        public void PRoomOpenMessage(IPEndPoint ip, string a)
        {
            try
            {
                byte[] sending = System.Text.Encoding.Unicode.GetBytes(a);
                UdpClient.Send(sending, sending.Length, ip);
            }
            catch (Exception E)
            {
                MessageBox.Show(E.ToString());
            }
        }

        public void SendMessageExit()
        {
            byte[] sending = System.Text.Encoding.Unicode.GetBytes("E");
            UdpClient.Send(sending, sending.Length, "255.255.255.255", 5000);
        }
        private void SendIHere()
        {
            while (true)
            {
                string m = ("S" + MessageNumber.ToString() + privateroomnumber.ToString() + sLocalUser);
                try
                {
                    byte[] send = System.Text.Encoding.Unicode.GetBytes(m);
                    UdpClient.Send(send, send.Length, "255.255.255.255", 5000);
                }
                catch (Exception E)
                {
                    MessageBox.Show(E.Message,"Kết nối mạng chưa có! ");
                }
                Thread.Sleep(20000);
            }
        }

        private void publicroom_NotifyDaddy(object sender, EventArgs e)
        {          
            string m = ((NotifyDaddyEventArgs)e).Message;
            SendMessageUdp(m);

        }
        private void publicroom_NotifyPrivate(object sender, EventArgs e)
        {
            string m = ((NotifyPrivateEventArgs)e).name;
            OpenPrivateRoom(m);
        }
        private void privates_NotifyPrivateSend(object sender, EventArgs e)
        {
            string m = ((NotifyPrivateSendEventArgs)e).Message;
            MessageBox.Show(m.ToString());
        }
        private void uop_NotifyBecomeOnline(object sender, EventArgs e)
        {
            string m = ((NotifyDeleteEventArgs)e).Message;
            publicroom.WriteMessage(m + " ngừng kết nối ", MessageColor, FontTypeNum, BItype);
        }
        private void publicroom_NotifyEnter(object sender, EventArgs e)
        {
            string m = ((NotifyEnterEventArgs)e).Message;
            SendMessageUdp(m);
        }

        public void OpenPrivateRoom(string name)
        {
            privateroom = new frmPrivateChat();
            privateroom.Privareroomopen(++privateroomnumber, UserOnline.FindUserIp(name), sLocalUser, name);
            privateroomnumber = privateroomnumber + 2; ;
            PRoomOpenMessage(UserOnline.FindUserIp(name), "PO" + privateroomnumber.ToString());
            privateroom.Show();
        }


        #region StartChating

        private void StartChating(string username)
        {
            sLocalUser = username;
            try
            {
                UdpClient = new UdpClient(5000);
                toolStripStatusLabel.BackColor = Color.Green;
                toolStripStatusLabel.Text = "Đã đăng nhập";
                publicroom.NotifyDaddy += new EventHandler(publicroom_NotifyDaddy);
                publicroom.NotifyEnter += new EventHandler(publicroom_NotifyEnter);
                publicroom.NotifyPrivate += new EventHandler(publicroom_NotifyPrivate);

                UserOnline = new cUserOnline(IPLocalEndPoint, sLocalUser);

                threadudp = new Thread(new ThreadStart(waitForPackets));
                thrKeepAlive = new Thread(new ThreadStart(SendIHere));
                thrCheckOnline = new Thread(new ThreadStart(CheckOnlines));

                threadudp.IsBackground = true;
                thrKeepAlive.IsBackground = true;
                thrCheckOnline.IsBackground = true;

                threadudp.Start();
                thrKeepAlive.Start();
                thrCheckOnline.Start();
            }
            catch
            {
                MessageBox.Show("Không thể tạo phòng chat");
            }
        }

        #endregion

        private void mainwindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                SendMessageExit();
                threadudp.Abort();
                thrKeepAlive.Abort();
                thrCheckOnline.Abort();
            }
            catch
            {
            }
        }

        private void mainwindow_Load(object sender, EventArgs e)
        {
            StartChating(Dns.GetHostName());
        }


    }
}

 

      
      
